package com.ruoyi.framework.security.handle;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.framework.config.properties.CasProperties;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.TokenService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.Principal;


@Service
public class CasAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	protected final Log logger = LogFactory.getLog(this.getClass());

	private RequestCache requestCache = new HttpSessionRequestCache();

	@Autowired
	private TokenService tokenService;

	@Autowired
	private CasProperties casProperties;

	/**
	 * 令牌有效期（默认30分钟）
	 */
	@Value("${token.expireTime}")
	private int expireTime;

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
										Authentication authentication) throws ServletException, IOException {
		String targetUrlParameter = getTargetUrlParameter();
		logger.info("调用了onAuthenticationSuccess"+targetUrlParameter);
		if (isAlwaysUseDefaultTargetUrl()
				|| (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
			requestCache.removeRequest(request, response);
			super.onAuthenticationSuccess(request, response, authentication);
			logger.info("调用了onAuthenticationSuccess进入了return");
			return;
		}
		//11-07
		Object credentials = authentication.getCredentials();
		String ticket = (String) credentials;
		//设置后端认证成功标识
		HttpSession httpSession = request.getSession();
		Object newTicket = httpSession.getAttribute("_ticket"); //该 newTicket 为最新的ticket

		//2023-08-22 获取自定义输入的URL,从session中获取目标路径进行重定向跳转
		String targetUrl = determineTargetUrl(request, response);
		if(null == targetUrl){
			logger.info("targetUrl为空");
			targetUrl="/";
		}
		logger.info("请求的url："+targetUrl);

		logger.info("调用了onAuthenticationSuccess: newTicket:"+newTicket);
		String ticketValidateUrl = UriComponentsBuilder.fromHttpUrl(casProperties.getCasServerUrl() + "/p3/serviceValidate")
				//				.queryParam("service", casProperties.getAppServerUrl() + "/")
				// 统一认证中心的service是前端最后的重定向跳转地址
				.queryParam("service", casProperties.getAppServerUrl() + "/?redirect_uri="+targetUrl)
				//				.queryParam("ticket", ticket)
				.queryParam("ticket", newTicket)
				.queryParam("format", "json")
				.toUriString();
		String res = HttpUtils.sendGet(ticketValidateUrl);
		logger.info("统一认证中心交互返回结果：res:"+res);

		Principal userPrincipal = request.getUserPrincipal();
		if(null != userPrincipal){
			AttributePrincipal principal = (AttributePrincipal) userPrincipal;
			logger.info("principal为："+ JSON.toJSONString(principal));
		}
		logger.info("调用了onAuthenticationSuccess: getPrincipal:"+authentication.getPrincipal());

		clearAuthenticationAttributes(request);
		LoginUser userDetails = (LoginUser) authentication.getPrincipal();
		String token = tokenService.createToken(userDetails);
		//往Cookie中设置token
		Cookie casCookie = new Cookie(Constants.WEB_TOKEN_KEY, token);
		casCookie.setMaxAge(expireTime * 60);
		response.addCookie(casCookie);

		httpSession.setAttribute(Constants.CAS_TOKEN, token);
		logger.info("准备执行重定向");

		// 保存登录成功日志
		LoginUser loginUser = tokenService.getLoginUser(request);
		if (com.ruoyi.common.utils.StringUtils.isNotNull(loginUser)){
			String userName = loginUser.getUsername();
			AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGIN_SUCCESS, "登录成功"));
		}

		//登录成功后跳转到前端登录页面
		getRedirectStrategy().sendRedirect(request, response, casProperties.getWebUrl()+"?token="+token+"&target_url="+targetUrl);
	}


	/**
	 * 2023-08-22
	 * @param request
	 * @param response
	 * @return
	 */
	@Override
	protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
		HttpSession session = request.getSession();
		if(session == null){
			return null;
		}
		Object attribute = session.getAttribute(request.getSession().getId());
		if(attribute == null){
			return null;
		}
		logger.info("attribute="+JSON.toJSONString(attribute));
		String defaultTargetUrl = attribute.toString();
		return defaultTargetUrl;
	}
}